﻿#include "socket.h"
#include "channel.h"
#include "eventloop.h"
#include "connection.h"
#include <iostream>
#include <unordered_map>

std::unordered_map<int, ConnectionPtr> g_conn_map;

void ConnectionEstablish(const ConnectionPtr &conn)
{
    int client_fd = conn->getSockfd();
    g_conn_map.insert(std::make_pair(client_fd, conn));
    std::cout << "server establish connection" << std::endl;
}

void MessageHandler(const ConnectionPtr &conn, Buffer *buf)
{
    std::cout << "server recv: " << buf->getReadAddr() << std::endl;
    buf->moveReadStep(buf->getReadSize());
    std::string response = "sfwnb";
    conn->send(response.c_str(), response.size());
    // TEST: 测试连接关闭是否有效
    conn->shutDown();
}


void ConnectionDestroy(const ConnectionPtr &conn)
{
    int client_fd = conn->getSockfd();
    auto it = g_conn_map.find(client_fd);
    if(it != g_conn_map.end())
    {
        g_conn_map.erase(it);
    }
}


bool AcceptNewClient(EventLoop *eloop, Channel *channel)
{
    int listen_fd = channel->getFd();
    int client_fd = accept(listen_fd, NULL, NULL);
    if(client_fd < 0)
    {
        std::cout << "accept failed, listen_fd: " << listen_fd << std::endl;
        return false;
    }

    // 创建连接
    uint64_t conn_id = 3;
    ConnectionPtr conn = std::make_shared<Connection>(eloop, conn_id, client_fd);
    // 设置回调
    conn->setMessageCallback(std::bind(MessageHandler, std::placeholders::_1, std::placeholders::_2));
    conn->setCloseCallback(std::bind(ConnectionDestroy, std::placeholders::_1));
    conn->setConnectCallback(std::bind(ConnectionEstablish, std::placeholders::_1));
    conn->enableInactiveRelease(10);
    conn->establishConnection();
    
    return true;
}

int main() 
{
    // 创建epoller
    EventLoop eloop;
    Socket socket;
    socket.createTcpServer(58888);
    socket.reuseAddress();
    // 创建channel
    Channel channel(&eloop, socket.fd());
    // 添加可读监控
    channel.setReadCallback(std::bind(AcceptNewClient, &eloop, &channel));
    channel.enableRead();

    eloop.start();

    socket.close();
    return 0;
} 